package com.wrt.wm.util;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.NoSuchElementException;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.FileImageInputStream;
import javax.media.jai.JAI;

import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.sun.media.jai.codec.PNGEncodeParam;

import lombok.extern.log4j.Log4j2;
import net.coobird.thumbnailator.Thumbnails;

/**
 * 重绘图片
 * 
 * @author 文瑞涛
 * @date 2020-7-27 16:32:01
 */
@Component
@Log4j2
public class RewriteImageUtil {

	@Value("${temppath.temp:temp}")
	private String temp;
	
	/**
	 * 
	 * 处理图片重绘
	 * 
	 * @param suffix 图片后缀名
	 * @param imgFile 图片文件对象
	 * @param img 图像缓冲器
	 * 
	 * @return 重绘后的图片地址
	 *
	 */
	public String handle(String suffix, File imgFile, BufferedImage img) {
		String path = temp;
		File temp = new File(path);
		if (!temp.exists()) {
			temp.mkdir();
		}
		String fileBaseName = FilenameUtils.getBaseName(imgFile.getName());
		switch (suffix) {
		case "jfif":
			path = path + File.separator + fileBaseName + ".jpg";
			jfif(img, path);
			break;
		case "tiff":
		case "tif":
			path = path + File.separator + fileBaseName + ".png";
			tiff(imgFile, path);
			break;
		default:
			path = path + File.separator + fileBaseName + "." + suffix;
			normal(img, path);
			break;
		}
		return path;
	}

	/**
	 * 
	 * 普通图像处理
	 * 
	 * @param img 图像缓冲器
	 * @param path 图片地址
	 *
	 */
	private void normal(BufferedImage img, String path) {
		try {
			Thumbnails.of(img).scale(1.0).toFile(path);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
	}

	/**
	 * 
	 * jfif图像处理
	 * 
	 * @param img 图像缓冲器
	 * @param path 图片地址
	 *
	 */
	private void jfif(BufferedImage img, String path) {
		try {
			Thumbnails.of(img).scale(1.0).outputFormat("jpg").toFile(path);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
	}

	/**
	 * 生成tiff原始dpi的png
	 * 
	 * @param tifFile 原始tif文件
	 * @param path    目标png
	 */
	private void tiff(File tifFile, String path) {
		Object[] src = readTiff(tifFile);
		if (src.length == 0) {
			return;
		}

		ImageReader reader = null;

		try (FileOutputStream os = new FileOutputStream(new File(path));
				FileImageInputStream fis = (FileImageInputStream) src[1];) {
			reader = (ImageReader) src[0];
			if (reader != null) {
				int numPages = reader.getNumImages(true);
				if (numPages > 0) {
					long[] dpiData = getTiffDpi(reader, 0);
					BufferedImage img = reader.read(0);

					double meter2inchRatio = 1d / 0.0254d;
					int dimX = (int) (dpiData[0] * meter2inchRatio) + 1;
					int dimY = (int) (dpiData[0] * meter2inchRatio) + 1;

					int scal = (Math.abs(dpiData[0] - dpiData[1]) <= 10) ? 1 : 2;

					int width = img.getWidth();
					int height = img.getHeight() * scal;

					// 图像起始x位置
					int drawPtX = 0;
					// 图像起始Y位置
					int drawPtY = 0;

					BufferedImage decImg = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
					Graphics2D g2 = decImg.createGraphics();
					g2.fillRect(0, 0, width, height);

					g2.drawImage(img.getScaledInstance(width, height, Image.SCALE_SMOOTH), drawPtX, drawPtY, null);

					PNGEncodeParam paramEnc = PNGEncodeParam.getDefaultEncodeParam(decImg);
					paramEnc.setPhysicalDimension(dimX, dimY, 1);
					JAI.create("encode", decImg, os, "png", paramEnc);
					os.flush();
				}
			}
		} catch (Exception e) {
			log.error("tif文件转换异常", e);
		} finally {
			if (reader != null) {
				reader.dispose();
			}
		}
	}

	/**
	 * 
	 * 读取tiff文件到 ImageReader
	 * Object[0]：ImageReader ,Object[1]:FileImageInputStream
	 * 
	 * @param tifFile tif文件对象
	 * 
	 * @return 对象数组，存放图像读取对象和图像文件输入流
	 * 
	 */
	private Object[] readTiff(File tifFile) {
		ImageReader reader = null;
		Object[] res = new Object[0];
		FileImageInputStream fis = null;
		try {
			Iterator<ImageReader> temp0 = ImageIO.getImageReadersByFormatName("tiff");
			Iterator<ImageReader> temp1 = ImageIO.getImageReadersByFormatName("tif");
			if (temp0.hasNext()) {
				reader = temp0.next();
			} else if (temp1.hasNext()) {
				reader = temp1.next();
			} else {
				return res;
			}
			fis = new FileImageInputStream(tifFile);
			reader.setInput(fis);
			res = new Object[] { reader, fis };
		} catch (NoSuchElementException e) {
			log.error("元素获取错误", e);
		} catch (Exception e) {
			log.error("tiff文件获取其他异常", e);
		}
		return res;
	}

	/**
	 * 
	 * 获取tiff dpi
	 * @param reader 图像读取对象
	 * @param index 序号
	 * 
	 * @return dpi数组
	 * 
	 */
	private long[] getTiffDpi(ImageReader reader, int index) {
		long[] dpi = new long[2];
		IIOMetadata meta = null;
		try {
			meta = reader.getImageMetadata(index);
			org.w3c.dom.Node n = meta.getAsTree("javax_imageio_1.0");
			n = n.getFirstChild();
			while (n != null) {
				if ("Dimension".equals(n.getNodeName())) {
					org.w3c.dom.Node n2 = n.getFirstChild();
					while (n2 != null) {
						if ("HorizontalPixelSize".equals(n2.getNodeName())) {
							org.w3c.dom.NamedNodeMap nnm = n2.getAttributes();
							org.w3c.dom.Node n3 = nnm.item(0);
							float hps = Float.parseFloat(n3.getNodeValue());
							dpi[0] = Math.round(25.4f / hps);
						}
						if ("VerticalPixelSize".equals(n2.getNodeName())) {
							org.w3c.dom.NamedNodeMap nnm = n2.getAttributes();
							org.w3c.dom.Node n3 = nnm.item(0);
							float vps = Float.parseFloat(n3.getNodeValue());
							dpi[1] = Math.round(25.4f / vps);
						}
						n2 = n2.getNextSibling();
					}
				}
				n = n.getNextSibling();
			}
		} catch (IOException e) {
			log.error("tif获取dpi异常", e);
		}
		return dpi;
	}

}
